package com.example.mvvm.base;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.os.Message;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;

import com.example.mvvm.R;
import com.example.mvvm.base.livedata.MessageLiveEvent;
import com.example.mvvm.base.livedata.StatusLiveEvent;
import com.example.mvvm.utils.ActivityManageUtils;
import com.example.mvvm.utils.DebugUtils;
import com.example.mvvm.utils.ScreenUtils;
import com.jaeger.library.StatusBarUtil;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public abstract class BaseActivity<VM extends BaseViewModel, VDB extends ViewDataBinding> extends AppCompatActivity implements IBaseView<VM> {

    /**
     * 请通过 {@link #getViewModel()}获取
     */
    private VM mViewModel;
    /**
     * 请通过 {@link #getBinding()}获取
     */
    private VDB mBinding;
    private Dialog dialog;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityManageUtils.getInstance().pushActivity(this);
        initContentView();
        if (isTranslucent()) {
            StatusBarUtil.setTranslucentForImageView(this, 0, null);
            StatusBarUtil.setLightMode(this);
        }
        initViewModel();
        initData(savedInstanceState);
    }



    /**
     * 初始化ContentView，{@link #setContentView(int)} }
     */
    protected void initContentView() {
        if (getLayoutId() == 0) return;
        if (isBinding()) {
            mBinding = DataBindingUtil.setContentView(this, getLayoutId());
            // 获取状态栏空间
            Toolbar toolbar = mBinding.getRoot().findViewById(R.id.tool_bar);
            // 控件为空的时候直接返回
            if (toolbar == null) return;
            // 获取状态栏高度
            int statusBarHeight = ScreenUtils.getStatusBarHeight(this.getApplicationContext());
            // 获取状态栏控件参数
            ViewGroup.LayoutParams params = toolbar.getLayoutParams();
            // 设置状态栏高度
            params.height = statusBarHeight;
            // 设置状态栏参数
            toolbar.setLayoutParams(params);
            DebugUtils.printfError("StatusBarHeight = " + statusBarHeight);
        } else {
            setContentView(getLayoutId());
        }
    }

    /**
     * 初始化 {@link #mViewModel}
     */
    private void initViewModel() {
        mViewModel = createViewModel();
        if (mViewModel != null) {
            getLifecycle().addObserver(mViewModel);
            mBinding.setVariable(variableId(), mViewModel);
            // 显示弹窗
            registerLoadingEvent();
        }
    }

    private Class<VM> getVMClass() {
        Class cls = getClass();
        Class<VM> vmClass = null;
        while (vmClass == null && cls != null) {
            vmClass = getVMClass(cls);
            cls = cls.getSuperclass();
        }
        if (vmClass == null) {
            vmClass = (Class<VM>) BaseViewModel.class;
        }
        return vmClass;
    }

    private Class getVMClass(Class cls) {
        Type type = cls.getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            Type[] types = ((ParameterizedType) type).getActualTypeArguments();
            for (Type t : types) {
                if (t instanceof Class) {
                    Class vmClass = (Class) t;
                    if (BaseViewModel.class.isAssignableFrom(vmClass)) {
                        return vmClass;
                    }
                } else if (t instanceof ParameterizedType) {
                    Type rawType = ((ParameterizedType) t).getRawType();
                    if (rawType instanceof Class) {
                        Class vmClass = (Class) rawType;
                        if (BaseViewModel.class.isAssignableFrom(vmClass)) {
                            return vmClass;
                        }
                    }
                }
            }
        }

        return null;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mViewModel != null) {
            getLifecycle().removeObserver(mViewModel);
            mViewModel = null;
        }

        if (mBinding != null) {
            mBinding.unbind();
            mBinding = null;
        }
    }

    public Context getContext() {
        return this;
    }

    /**
     * 是否使用DataBinding
     *
     * @return 默认为true 表示使用。如果为false，则不会初始化 {@link #mBinding}。
     */
    @Override
    public boolean isBinding() {
        return true;
    }

    /**
     * 是否透明状态栏
     *
     * @return true透明状态栏 false不是透明状态栏
     */
    @Override
    public boolean isTranslucent() {
        return true;
    }

    /**
     * 创建ViewModel
     *
     * @return {@link #mViewModel}会默认根据当前Activity泛型 {@link VM}获得ViewModel
     */
    @Override
    public VM createViewModel() {
        return obtainViewModel(getVMClass());
    }

    /**
     * 获取 ViewModel
     *
     * @return {@link #mViewModel}
     */
    public VM getViewModel() {
        return mViewModel;
    }

    /**
     * 获取 ViewDataBinding
     *
     * @return {@link #mBinding}
     */
    public VDB getBinding() {
        return mBinding;
    }

    /**
     * 通过 {@link #createViewModelProvider(ViewModelStoreOwner)}获得 ViewModel
     *
     * @param modelClass Class
     * @return ViewModel
     */
    public <T extends ViewModel> T obtainViewModel(@NonNull Class<T> modelClass) {
        return createViewModelProvider(this).get(modelClass);
    }

    /**
     * @param modelClass modelClass
     * @return ViewModel
     * @deprecated 请使用 {@link #obtainViewModel(Class)}
     */
    @Deprecated
    public <T extends ViewModel> T getViewModel(@NonNull Class<T> modelClass) {
        return obtainViewModel(modelClass);
    }

    /**
     * 创建 {@link ViewModelProvider}
     *
     * @param owner ViewModelStoreOwner实例对象
     * @return 返回实例
     */
    private ViewModelProvider createViewModelProvider(@NonNull ViewModelStoreOwner owner) {
        return new ViewModelProvider(owner, ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication()));
    }

    /**
     * 注册状态加载事件
     */
    protected void registerLoadingEvent() {
        mViewModel.getLoadingEvent().observe(this, isLoading -> {
            if (isLoading) {
                showLoading();
            } else {
                hideLoading();
            }
        });
    }

    @Override
    public void showLoading() {
        showProgressDialog();
    }

    private void showProgressDialog() {
        showProgressDialog(R.layout.layout_loading, false);
    }

    private void showProgressDialog(@LayoutRes int layoutId, boolean cancel) {
        dialog = new Dialog(this, R.style.user_default_dialog);
        dialog.setContentView(layoutId);
        dialog.getWindow().setGravity(Gravity.CENTER);
        dialog.setCanceledOnTouchOutside(cancel);
        dialog.show();
    }

    @Override
    public void hideLoading() {
        dismissProgressDialog();
    }

    private void dismissProgressDialog() {
        dismissDialog(dialog);
    }

    private void dismissDialog(Dialog dialog) {
        if (dialog != null && dialog.isShowing()) {
            dialog.dismiss();
        }
    }

    /**
     * 注册消息事件
     */
    protected void registerMessageEvent(@NonNull MessageLiveEvent.MessageObserver observer) {
        getViewModel().getMessageEvent().observe(this, observer);
    }

    /**
     * 注册单个消息事件，消息对象:{@link Message}
     *
     * @param observer 消息
     */
    protected void registerSingleLiveEvent(@NonNull Observer<Message> observer) {
        getViewModel().getSingleLiveEvent().observe(this, observer);
    }

    /**
     * 注册状态事件
     *
     * @param observer 状态
     */
    protected void registerStatusEvent(@NonNull StatusLiveEvent.StatusObserver observer) {
        getViewModel().getStatusEvent().observe(this, observer);
    }

    protected DisplayMetrics getDisplayMetrics() {
        return getResources().getDisplayMetrics();
    }

    protected int getWidthPixels() {
        return getDisplayMetrics().widthPixels;
    }

    protected int getHeightPixels() {
        return getDisplayMetrics().heightPixels;
    }

}
